﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using BussinesLayer.Clases;
using CustomControl;
using DTO.Clases;
using Utilities;
using Aplicacion.Compras.IngresarCompra;
using Microsoft.Reporting.WinForms;

namespace Aplicacion.Ventas.Factura
{
    public partial class FrmFacturaVenta : Form
    {
        #region Logica de Negocio

        /// <summary>
        /// Objeto que encapsula la lógica de negocio de Forma de Pago.
        /// </summary>
        //private BussinesFormaPago miBussinesFormaPago;
        private BussinesEstado miBussinesEstado;

        /// <summary>
        /// Objeto que encapsula la lógica de negocio de Empresa.
        /// </summary>
        private BussinesEmpresa miBussinesEmpresa;

        /// <summary>
        /// Objeto que encapsula la lógica de negocio de Factura Venta.
        /// </summary>
        private BussinesFacturaVenta miBussinesFactura;

        /// <summary>
        /// Objeto que encapsula la lógica de negocio de Cliente.
        /// </summary>
        private BussinesCliente miBussinesCliente;

        /// <summary>
        /// Objeto que encapsula la lógica de negocio de Producto.
        /// </summary>
        private BussinesProducto miBussinesProducto;

        /// <summary>
        /// Objeto que encapsula la lógica de negocio de Valor de Unidad de Medida.
        /// </summary>
        private BussinesValorUnidadMedida miBussinesMedida;

        /// <summary>
        /// Objeto que encapsula la lógica de negocio de Color.
        /// </summary>
        private BussinesColor miBussinesColor;

        /// <summary>
        /// Objeto que encapsula la lógica de negocio de Descuento.
        /// </summary>
        private BussinesDescuento miBussinesDescuento;

        /// <summary>
        /// Objeto que encapsula la lógica de negocio de Recargo.
        /// </summary>
        private BussinesRecargo miBussinesRecargo;

        private BussinesUsuario miBussinesUsuario;

        private BussinesDian miBussinesDian;

        #endregion

        #region Propiedades

        /// <summary>
        /// Representa un objeto para la carga de datos de la Empresa.
        /// </summary>
        private Empresa miEmpresa;

        private bool FacturaPos { set; get; }

        /// <summary>
        /// Representa una tabla de datos en memoria.
        /// </summary>
        private DataTable miTabla;

        /// <summary>
        /// Representa un objeto para la carga de datos de Factura de Venta.
        /// </summary>
        private FacturaVenta miFactura;

        public bool Edicion { set; get; }

        public FacturaVenta Factura { set; get; }

        public DataTable Productos { set; get; }

        

        /// <summary>
        /// Representa un objeto para la carga de datos de Forma Pago.
        /// </summary>
        private List<DTO.Clases.FormaPago> miFormasPago;

        /// <summary>
        /// Obtiene o establece el valor de la fecha en que se ingresa la factura.
        /// </summary>
        private DateTime FechaHoy;

        /// <summary>
        /// Obtiene o establece el Nit del Cliente.
        /// </summary>
        private string NitCliente;

        /// <summary>
        /// Obtiene o establece el valor de Id del criterio de la Forma de Pago.
        /// </summary>
        private int IdEstado = 0;

        /// <summary>
        /// Obtiene o establece el valor de Id del criterio de descuento o recargo.
        /// </summary>
        private int IdDesctoRecgo = 0;

        /// <summary>
        /// Indica si se realiza un promedio de Facturas de Compra o 
        /// se tiene en cuenta la última, true indica promedio.
        /// </summary>
        private bool Promedio;

        /// <summary>
        /// Obtiene o establece el número de Facturas a promediar.
        /// </summary>
        private int NumeroDeFacturas;

        #endregion

        #region Utilidades

        /// <summary>
        /// Representa una pequeña ventana emergente que muestra una breve explicacion de la funcion del control.
        /// </summary>
        private ToolTip miToolTip;

        /// <summary>
        /// Representa un objeto para mostrar mensajes de error
        /// </summary>
        private ErrorProvider miError;

        /// <summary>
        /// Colección que almacena objetos, en este caso Productos.
        /// </summary>
        private ArrayList ArrayProducto;

        /// <summary>
        /// Objeto para cargar Producto.
        /// </summary>
        private DTO.Clases.Producto MiProducto;

        /// <summary>
        /// Objeto para cargar los datos de la medida del producto consultado.
        /// </summary>
        private ValorUnidadMedida miMedida;

        /// <summary>
        /// Objeto para la carga del talla y color del producto.
        /// </summary>
        private TallaYcolor miTallaYcolor;

        /// <summary>
        /// Representa una variable para realizar conteo.
        /// </summary>
        private int Contador = 0;

        /// <summary>
        /// Objeto que encapsula el origen de datos del DataGrid de Productos.
        /// </summary>
        private BindingSource miBindingSource;

        #endregion

        #region Validación

        /// <summary>
        /// Objeto que permite el acceso a la validación de datos.
        /// </summary>
        Validacion MiValidacion;

        /// <summary>
        /// Indica que se ha cargado la Talla y el Color desde el Boton Agregar Registro.
        /// </summary>
        private bool LoadColorSize = false;

        /// <summary>
        /// Obtiene o establece el valor que indica si se habilita color o no en el formulario segun la configuración.
        /// </summary>
        private bool EnableColor;

        /// <summary>
        /// Indica si el Producto tiene una sola talla.
        /// </summary>
        private bool SingleSize = false;

        /// <summary>
        /// Indica si el Producto tiene un solo color.
        /// </summary>
        private bool SingleColor = false;

        #endregion

        #region Mensajes

        /// <summary>
        /// Representa el texto: El documento del cliente es requerido.
        /// </summary>
        private string ClienteReq = "El documento del cliente es requerido.";

        /// <summary>
        /// Representa el texto: El número de documento que ingreso tiene formato incorrecto.
        /// </summary>
        private string ClienteFormato = "El número de documento que ingreso tiene formato incorrecto.";

        /// <summary>
        /// Representa el texto: El campo Codigo del Articulo es requerido.
        /// </summary>
        private string CodigoProductoReq = "El campo Codigo del Articulo es requerido.";

        /// <summary>
        /// Representa el texto: El Codigo del Articulo que ingreso tiene formato incorrecto.
        /// </summary>
        private string CodigoProductoFormato = "El Codigo del Articulo que ingreso tiene formato incorrecto.";

        /// <summary>
        /// Representa el texto: El Codigo del Articulo que ingreso no tiene registros en la base de datos.
        /// </summary>
        private string CodigoProductoExiste = "El Codigo del Articulo que ingreso no tiene registros en la base de datos.";

        #endregion

        public FrmFacturaVenta()
        {
            InitializeComponent();
            Edicion = false;
            miFactura = new FacturaVenta();
            //miBussinesFormaPago = new BussinesFormaPago();
            miBussinesEstado = new BussinesEstado();
            miBussinesEmpresa = new BussinesEmpresa();
            miBussinesFactura = new BussinesFacturaVenta();
            miBussinesDescuento = new BussinesDescuento();
            miBussinesRecargo = new BussinesRecargo();
            miBussinesCliente = new BussinesCliente();
            miBussinesProducto = new BussinesProducto();
            miBussinesMedida = new BussinesValorUnidadMedida();
            miBussinesColor = new BussinesColor();
            miBussinesUsuario = new BussinesUsuario();
            miBussinesDian = new BussinesDian();
            CargarEmpresa();
            miFormasPago = new List<DTO.Clases.FormaPago>();
            FechaHoy = DateTime.Now;
            FacturaPos = Convert.ToBoolean(AppConfiguracion.ValorSeccion("facturapos"));
            EnableColor = Convert.ToBoolean(AppConfiguracion.ValorSeccion("color"));
            Promedio = Convert.ToBoolean(AppConfiguracion.ValorSeccion("promedio"));
            NumeroDeFacturas = Convert.ToInt32(AppConfiguracion.ValorSeccion("numero"));
            miTallaYcolor = new TallaYcolor();
            MiValidacion = new Validacion();
            miError = new ErrorProvider();
            miToolTip = new ToolTip();
            Convert.ToBoolean(AppConfiguracion.ValorSeccion("color"));
            miBindingSource = new BindingSource();
            CrearDataTable();
            //ObtenerNumero();
        }

        private void FrmFacturaVenta_Load(object sender, EventArgs e)
        {
            //ObtenerNumero();
            NitCliente = txtCliente.Text;
            lblDataFecha.Text = FechaHoy.Day + " de " + UseDate.MesCorto(FechaHoy.Month) + " de " + FechaHoy.Year;
            CargarUtilidades();
            CompletaEventos.Completa += new CompletaEventos.CompletaAccion(CompletaEventos_Completo);
            CompletaEventos.Completam += new CompletaEventos.CompletaAccionm(CompletaEventosm_Completo);
            dgvListaArticulos.AutoGenerateColumns = false;
            dgvListaArticulos.DataSource = miBindingSource;
            if (Edicion)
            {
                CargarFacturaEdicion();
            }

            miFactura.Usuario = Administracion.Usuario.FrmIniciarSesion.CargarDatosUsuario(this);
        }

        private void FrmFacturaVenta_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyData == Keys.F5)
            {
                if (dgvListaArticulos.RowCount != 0)
                {
                    dgvListaArticulos.Focus();
                    dgvListaArticulos.EditMode = DataGridViewEditMode.EditOnEnter;
                    dgvListaArticulos.BeginEdit(true);
                }
                else
                {
                    OptionPane.MessageInformation("No hay registros para editar.");
                }
            }
            else
            {
                if (e.KeyData == Keys.F6)
                {
                    //Venta = true;
                    RealizarVenta();
                }
                else
                {
                    if (e.KeyData == Keys.F3)
                    {
                        btnBuscarCliente_Click(this.btnBuscarCliente, new EventArgs());
                    }
                    else
                    {
                        if (e.KeyData == Keys.F4)
                        {
                            if (!ExtendForms)
                            {
                                //derechos de administrador.
                                var formProducto = new Inventario.Producto.FrmIngresarProducto();
                                formProducto.MdiParent = this.MdiParent;
                                formProducto.Extencion = true;
                                formProducto.tabControlProducto.SelectedIndex = 1;
                                ExtendForms = true;
                                formProducto.Show();
                            }
                        }
                        else
                        {
                            if (e.KeyData == Keys.Escape)
                            {
                                this.Close();
                            }
                        }
                    }
                }
            }
        }

        private void FrmFacturaVenta_FormClosing(object sender, FormClosingEventArgs e)
        {

        }
        private bool contado = true;
        private void tsCbContado_SelectedIndexChanged(object sender, EventArgs e)
        {
            //if (dgvListaArticulos.RowCount == 0)
            //{
                IdEstado = Convert.ToInt32(((DataRowView)tsCbContado.SelectedItem)["idestado"]);
                if (IdEstado != 2)
                {
                    contado = true;
                    lblFecha.Text = "Fecha";
                    lblDataFecha.Visible = true;
                    dtpFechaLimite.Value = DateTime.Today;
                    dtpFechaLimite.Visible = false;
                    if (IdEstado == 1)
                    {
                        lblInfoEstado.Text = "Factura a Contado.";
                    }
                    else
                    {
                        lblInfoEstado.Text = "Factura Pendiente.";
                    }
                }
                else   //Credito
                {
                    lblInfoEstado.Text = "Factura a Crédito.";
                    contado = false;
                    lblFecha.Text = "Fecha Limte";
                    lblDataFecha.Visible = false;
                    dtpFechaLimite.Visible = true;
                }
                if (!Edicion)
                {
                    //ObtenerNumero();
                }
            /*}
            else
            {
                if (MsnEstado)
                {
                    OptionPane.MessageInformation
                            ("Este cambio no se puede realizar debido a que hay registros en la factura.");
                    MsnEstado = false;
                }
                tsCbContado.ComboBox.SelectedValue = IdEstado;
            }
            MsnEstado = true;*/
        }
        //private bool MsnEstado = true;
        //private bool ClienteKeyPress = false;
        private void tsCbDesctoRecargo_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (dgvListaArticulos.RowCount == 0)
            {
                IdDesctoRecgo = ((Inventario.Producto.Criterio)tsCbDesctoRecargo.SelectedItem).Id;
                if (IdDesctoRecgo == 1)
                {
                    lblDescuentoFactura.Text = "Descto/Fact";
                    lblDesctoProducto.Text = "Descto%";
                    miToolTip.SetToolTip(rbtnDesctoProducto, "Aplicar descuento por Producto.");
                    miToolTip.SetToolTip(pbProducto, "Aplicar descuento por Producto.");
                    miToolTip.SetToolTip(rbtnDesctoFactura, "Aplicar descuento por Factura.");
                    miToolTip.SetToolTip(pbFactura, "Aplicar descuento por Factura.");
                    if (cbRecargoProducto.Visible)
                    {
                        dgvListaArticulos.Columns["ValorMenosDescto"].Width = ValorMenosDescto.Width - 1;
                    }
                    dgvListaArticulos.Columns["Descuento"].HeaderText = "Descto";
                    dgvListaArticulos.Columns["ValorMenosDescto"].HeaderText = "Valor - Descto";
                    cbDescuentoProducto.Visible = true;
                    cbRecargoProducto.Visible = false;
                    rbtnDesctoFactura.Enabled = true;
                    rbtnDesctoProducto.Enabled = true;
                    txtDescuentoFactura.Enabled = true;
                }
                else
                {
                    if (IdDesctoRecgo == 2)
                    {
                        lblDescuentoFactura.Text = "Recargo/Fact";
                        lblDesctoProducto.Text = "Recargo%";
                        miToolTip.SetToolTip(rbtnDesctoProducto, "Aplicar recargo por Producto.");
                        miToolTip.SetToolTip(pbProducto, "Aplicar recargo por Producto.");
                        miToolTip.SetToolTip(rbtnDesctoFactura, "Aplicar recargo por Factura.");
                        miToolTip.SetToolTip(pbFactura, "Aplicar recargo por Factura.");
                        dgvListaArticulos.Columns["ValorMenosDescto"].Width = ValorMenosDescto.Width + 1;
                        dgvListaArticulos.Columns["Descuento"].HeaderText = "Recgo";
                        dgvListaArticulos.Columns["ValorMenosDescto"].HeaderText = "Valor + Recgo";
                        cbDescuentoProducto.Visible = false;
                        cbRecargoProducto.Visible = true;
                        rbtnDesctoFactura.Enabled = true;
                        rbtnDesctoProducto.Enabled = true;
                        txtDescuentoFactura.Enabled = true;
                    }
                    else
                    {
                        rbtnDesctoFactura.Enabled = false;
                        rbtnDesctoProducto.Enabled = false;
                        txtDescuentoFactura.Enabled = false;
                    }
                }
                //CargarDescuentosORecargos();
            }
            else
            {
                if (MsnDescto)
                {
                    OptionPane.MessageInformation
                            ("Este cambio no se puede realizar debido a que hay registros en la factura.");
                    MsnDescto = false;
                }
                tsCbDesctoRecargo.ComboBox.SelectedValue = IdDesctoRecgo;
            }
            MsnDescto = true;
        }

        private void tsCambiarPrecio_Click(object sender, EventArgs e)
        {
            this.FrmFacturaVenta_KeyDown(this, new KeyEventArgs(Keys.F5));
        }

        private void tsRealizarVenta_Click(object sender, EventArgs e)
        {
            this.FrmFacturaVenta_KeyDown(this, new KeyEventArgs(Keys.F6));
        }

        private void tsBtnSalir_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private bool MsnDescto = true;
        private void txtCliente_KeyPress(object sender, KeyPressEventArgs e)
        {
            //try
            //{
            if (e.KeyChar == (char)Keys.Enter)
            {
                //ClienteMatch = true;
                //txtCliente.Focus();
                if (ValidarCodigoCliente())
                {
                    if (ExisteCliente())
                    {
                        try
                        {
                            var cliente = miBussinesCliente.ClienteAEditar(txtCliente.Text);
                            txtNombreCliente.Text = cliente.NitCliente + " - " + cliente.NombresCliente;
                            NitCliente = cliente.NitCliente;
                            txtCodigoArticulo.Focus();
                            cliente = null;
                            ClienteMatch = true;
                        }
                        catch (Exception ex)
                        {
                            OptionPane.MessageError(ex.Message);
                        }
                    }
                    else
                    {
                        DialogResult rta = MessageBox.Show("El cliente que ingreso no existe.\n¿Desea Crearlo?",
                            "Factura Venta", MessageBoxButtons.YesNo, MessageBoxIcon.Information);
                        if (rta.Equals(DialogResult.Yes))
                        {
                            //txtCodigoArticulo.Focus();
                            if (!ExtendForms)
                            {
                                var frmCliente = new Cliente.frmCliente();
                                frmCliente.MdiParent = this.MdiParent;
                                frmCliente.FacturaVenta = true;
                                frmCliente.txtNit.Text = txtCliente.Text;
                                ClienteMatch = true;
                                frmCliente.Show();
                                ExtendForms = true;
                                frmCliente.txtNombres.Focus();
                            }
                        }
                    }
                }
            }
            else
            {
            }
            //}
            //catch (Exception ex)
            //{
            //    OptionPane.MessageError(ex.Message);
            //}
        }

        private void txtCliente_Validating(object sender, CancelEventArgs e)
        {
            if (!ClienteMatch)
            {
                //ClienteMatch = true;
                txtCliente_KeyPress(txtCliente, new KeyPressEventArgs((char)Keys.Enter));
            }
        }
        private bool ExtendForms = false;
        private void btnBuscarCliente_Click(object sender, EventArgs e)
        {
            if (!ExtendForms)
            {
                var frmCliente = new Cliente.frmCliente();
                frmCliente.MdiParent = this.MdiParent;
                frmCliente.tcClientes.SelectedIndex = 1;
                frmCliente.FacturaVenta = true;
                ClienteMatch = true;
                ExtendForms = true;
                frmCliente.Show();
                frmCliente.txtNit.Focus();
            }
        }

        private void rbtnDesctoProducto_Click(object sender, EventArgs e)
        {
            if (dgvListaArticulos.RowCount == 0)
            {
                if (IdDesctoRecgo == 1)
                {
                    txtDescuentoFactura.Enabled = false;
                    cbDescuentoProducto.Enabled = true;
                    cbRecargoProducto.Enabled = false;
                }
                else
                {
                    txtDescuentoFactura.Enabled = false;
                    cbDescuentoProducto.Enabled = false;
                    cbRecargoProducto.Enabled = true;
                }
                CargarDescuentosORecargos();
            }
            else
            {
                rbtnDesctoFactura.Checked = true;
                OptionPane.MessageInformation
                            ("Este cambio no se puede realizar debido a que hay registros en la factura.");
            }
        }

        private void rbtnDesctoFactura_Click(object sender, EventArgs e)
        {
            if (dgvListaArticulos.RowCount == 0)
            {
                if (IdDesctoRecgo == 1)
                {
                    txtDescuentoFactura.Enabled = true;
                    cbDescuentoProducto.Enabled = false;
                    cbRecargoProducto.Enabled = false;
                }
                else
                {
                    txtDescuentoFactura.Enabled = true;
                    cbDescuentoProducto.Enabled = false;
                    cbRecargoProducto.Enabled = false;
                }
            }
            else
            {
                rbtnDesctoProducto.Checked = true;
                OptionPane.MessageInformation
                            ("Este cambio no se puede realizar debido a que hay registros en la factura.");
            }
        }

        private void txtCantidad_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == (char)Keys.Enter)
            {
                if (String.IsNullOrEmpty(txtCantidad.Text))
                {
                    txtCantidad.Text = "1";
                    txtCodigoArticulo.Focus();
                }
                else
                {
                    if (Validacion.ConFormato
                        (Validacion.TipoValidacion.Numeros, txtCantidad, miError, "La cantidad que ingreso tiene formato incorrecto."))
                    {
                        txtCodigoArticulo.Focus();
                    }
                    else
                    {
                        txtCantidad.Focus();
                    }
                }
            }
        }

        private void txtCodigoArticulo_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == (char)Keys.Enter)
            {
                if (CodigoOrString())
                {
                    if (ExisteProducto(txtCodigoArticulo.Text))
                    {
                        if (CargarProducto())
                        {
                            //CargarDescuentosORecargos();
                            if (cbDescuentoProducto.Enabled)
                            {
                                cbDescuentoProducto.Focus();
                            }
                            else
                            {
                                if (cbRecargoProducto.Enabled)
                                {
                                    cbRecargoProducto.Focus();
                                }
                                else
                                {
                                    if (MiProducto.AplicaTalla || MiProducto.AplicaColor)
                                    {
                                        if (!SingleSize || !SingleColor)
                                        {
                                            btnTallaYcolor_Click(this.btnTallaYcolor, new EventArgs());
                                        }
                                        else
                                        {
                                            EstructurarConsulta();
                                            return;
                                        }
                                        //btnTallaYcolor.Focus();
                                    }
                                }
                            }
                            if (!cbDescuentoProducto.Enabled && !cbRecargoProducto.Enabled && !btnTallaYcolor.Enabled)
                            {
                                EstructurarConsulta();
                                //FrmFacturaVenta_KeyDown(this, new KeyEventArgs(Keys.F12));
                            }
                            /* if (MiProducto.AplicaTalla || MiProducto.AplicaColor)
                             {
                                 if ((MiProducto.AplicaTalla && miTallaYcolor.IdTalla == 0) ||
                                     (MiProducto.AplicaColor && miTallaYcolor.IdColor == 0))
                                 {
                                     LoadColorSize = true;
                                     btnTallaYcolor_Click(this.btnTallaYcolor, new EventArgs());
                                     return;
                                 }
                                 else
                                 {
                                     LoadColorSize = false;
                                     EstructurarConsulta();
                                 }
                             }*/
                            //EstructurarConsulta();
                        }
                    }
                    else
                    {
                        DialogResult rta = MessageBox.Show("El Producto no existe.\n¿Desea Crearlo?",
                                "Factura Venta", MessageBoxButtons.YesNo, MessageBoxIcon.Information);
                        if (rta.Equals(DialogResult.Yes))
                        {
                            if (!ExtendForms)
                            {
                                //derechos de administrador.
                                var formProducto = new Inventario.Producto.FrmIngresarProducto();
                                formProducto.MdiParent = this.MdiParent;
                                ExtendForms = true;
                                formProducto.Show();
                            }
                        }
                    }
                }
                else
                {
                }
            }
        }

        private void txtCodigoArticulo_Validating(object sender, CancelEventArgs e)
        {

        }

        private void cbDescuentoProducto_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == (char)Keys.Enter)
            {
                if (MiProducto.AplicaTalla || MiProducto.AplicaColor)
                {
                    if ((MiProducto.AplicaTalla && miTallaYcolor.IdTalla == 0) ||
                        (MiProducto.AplicaColor && miTallaYcolor.IdColor == 0))
                    {
                        LoadColorSize = true;
                        btnTallaYcolor_Click(this.btnTallaYcolor, new EventArgs());
                        return;
                    }
                    else
                    {
                        LoadColorSize = false;
                        EstructurarConsulta();
                    }
                }
                else
                {
                    EstructurarConsulta();
                }
            }
        }

        private void cbRecargoProducto_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == (char)Keys.Enter)
            {
                if (MiProducto.AplicaTalla || MiProducto.AplicaColor)
                {
                    if ((MiProducto.AplicaTalla && miTallaYcolor.IdTalla == 0) ||
                        (MiProducto.AplicaColor && miTallaYcolor.IdColor == 0))
                    {
                        LoadColorSize = true;
                        btnTallaYcolor_Click(this.btnTallaYcolor, new EventArgs());
                        return;
                    }
                    else
                    {
                        LoadColorSize = false;
                        EstructurarConsulta();
                    }
                }
                else
                {
                    EstructurarConsulta();
                }
            }
        }

        private void btnTallaYcolor_Click(object sender, EventArgs e)
        {
            if (MiProducto != null)
            {
                if (MiProducto.AplicaTalla || MiProducto.AplicaColor)
                {
                    var FrmTallaColor = new frmMedidaColor();
                    FrmTallaColor.MdiParent = this.MdiParent;
                    FrmTallaColor.AplicaTalla = MiProducto.AplicaTalla;
                    FrmTallaColor.AplicaColor = MiProducto.AplicaColor;
                    FrmTallaColor.CodigoProducto = MiProducto.CodigoInternoProducto;
                    if (MiProducto.AplicaColor && !MiProducto.AplicaTalla) //COLOR Y NO TALLA
                    {
                        FrmTallaColor.IdMedida_ = miMedida.IdValorUnidadMedida;
                    }
                    if (EnableColor && MiProducto.AplicaColor)
                    {
                        FrmTallaColor.Show();
                    }
                    else
                    {
                        if (MiProducto.AplicaTalla)
                        {
                            FrmTallaColor.AplicaColor = false;
                            FrmTallaColor.Show();
                        }
                    }
                }
            }
            else
            {
                OptionPane.MessageInformation("Debe selecciona un Articulo primero.");
            }
        }

        private void dgvListaArticulos_CellValidating(object sender, DataGridViewCellValidatingEventArgs e)
        {
            if (e.ColumnIndex == 8)
            {
                if (!String.IsNullOrEmpty(e.FormattedValue.ToString()))
                {
                    if (!MiValidacion.ValidarNumeroInt(e.FormattedValue.ToString()))
                    {
                        OptionPane.MessageError("El número que ingreso es incorrecto.");
                        e.Cancel = true;
                    }
                    else
                    {
                        ActualizarInformacion(e.RowIndex, e.FormattedValue.ToString());
                        return;
                    }
                }
                else
                {
                    OptionPane.MessageError("Debe ingresar un valor.");
                    e.Cancel = true;
                }
            }
        }

        //metodos...

        /// <summary>
        /// Carga los valores de las utilizados en el Formulario de Factura de Venta.
        /// </summary>
        private void CargarUtilidades()
        {
            var lst = new List<Inventario.Producto.Criterio>();
            lst.Add(new Inventario.Producto.Criterio
            {
                Id = 0,
                Nombre = ""
            });
            lst.Add(new Inventario.Producto.Criterio
            {
                Id = 1,
                Nombre = "Descuento"
            });
            lst.Add(new Inventario.Producto.Criterio
            {
                Id = 2,
                Nombre = "Recargo"
            });
            tsCbDesctoRecargo.ComboBox.DataSource = lst;
            tsCbDesctoRecargo.ComboBox.DisplayMember = "Nombre";
            tsCbDesctoRecargo.ComboBox.ValueMember = "Id";
            try
            {
                tsCbContado.ComboBox.DisplayMember = "descripcionestado";
                tsCbContado.ComboBox.ValueMember = "idestado";
                tsCbContado.ComboBox.DataSource = miBussinesEstado.Lista();
            }
            catch (Exception ex)
            {
                OptionPane.MessageError(ex.Message);
            }

            miToolTip.SetToolTip(btnBuscarCliente, "Buscar Cliente [F3]");
            miToolTip.SetToolTip(txtCodigoArticulo, "Buscar Producto [F4]");

            miToolTip.SetToolTip(btnTallaYcolor, "Seleccionar Talla y Color");
            miToolTip.SetToolTip(rbtnDesctoProducto, "Aplicar descuento por Producto.");
            miToolTip.SetToolTip(pbProducto, "Aplicar descuento por Producto.");
            miToolTip.SetToolTip(rbtnDesctoFactura, "Aplicar descuento por Factura.");
            miToolTip.SetToolTip(pbFactura, "Aplicar descuento por Factura.");
        }

        /// <summary>
        /// Carga en memoria los datos de la Empresa.
        /// </summary>
        private void CargarEmpresa()
        {
            try
            {
                miEmpresa = miBussinesEmpresa.ObtenerEmpresa();
            }
            catch (Exception ex)
            {
                OptionPane.MessageError(ex.Message);
            }
        }

        /// <summary>
        /// Obtiene el Número consecutivo a ser asignado en la Factura.
        /// </summary>
        /// <returns></returns>
        private void ObtenerNumero()
        {
            try
            {
                long numero = 0;
                var numeroBD = miBussinesFactura.ObtenerNumero(contado);
                try
                {
                    numero = Convert.ToInt64(numeroBD);
                }
                catch
                {
                    var num = numeroBD.Split('-');
                    numero = Convert.ToInt64(num[1]);
                    num = null;
                }
                if (numero > miBussinesFactura.ObtenerRangoFinal(contado))
                {
                    MessageBox.Show("El número de la factura exede numero de registro asignado por la DIAN.",
                        "Factura Venta", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                }
                lblNoFactura.Text = numeroBD;
                miFactura.Numero = numeroBD;
                numeroBD = null;
            }
            catch (Exception ex)
            {
                OptionPane.MessageError(ex.Message);
            }
        }

        /// <summary>
        /// Obtiene un Número consecutivo temporal para ser asignado en la Factura.
        /// </summary>
        /// <returns></returns>
        private string ObtenerNumeroTemp()
        {
            return
            AppConfiguracion.ValorSeccion("const") + AppConfiguracion.ValorSeccion("numero");
        }

        /// <summary>
        /// Incrementa en una unidad el número designado como consecutivo temporal.
        /// </summary>
        private void ActualizaNumeroTemp()
        {
            var numero = Convert.ToInt64(AppConfiguracion.ValorSeccion("numero"));
            numero++;
            AppConfiguracion.SaveConfiguration("numero", numero.ToString());
        }

        /// <summary>
        /// Crea las respectivas columnas del DataTable miTabla.
        /// </summary>
        private void CrearDataTable()
        {
            miTabla = new DataTable();
            miTabla.Columns.Add(new DataColumn("Id", typeof(int)));
            miTabla.Columns.Add(new DataColumn("Codigo", typeof(string)));
            miTabla.Columns.Add(new DataColumn("Articulo", typeof(string)));
            miTabla.Columns.Add(new DataColumn("Cantidad", typeof(string)));
            miTabla.Columns.Add(new DataColumn("ValorUnitario", typeof(int)));
            miTabla.Columns.Add(new DataColumn("Descuento", typeof(string)));
            miTabla.Columns.Add(new DataColumn("ValorMenosDescto", typeof(double)));
            miTabla.Columns.Add(new DataColumn("Iva", typeof(string)));
            miTabla.Columns.Add(new DataColumn("TotalMasIva", typeof(double)));
            miTabla.Columns.Add(new DataColumn("Valor", typeof(double)));
            miTabla.Columns.Add(new DataColumn("Unidad", typeof(string)));
            miTabla.Columns.Add(new DataColumn("IdMedida", typeof(int)));
            miTabla.Columns.Add(new DataColumn("Medida", typeof(string)));
            miTabla.Columns.Add(new DataColumn("IdColor", typeof(int)));
            miTabla.Columns.Add(new DataColumn("Color", typeof(Image)));
            miTabla.Columns.Add(new DataColumn("Save", typeof(bool)));
        }

        /// <summary>
        /// Valida que el documento del cliente ingresado no sea vacío y tenga formato correcto.
        /// </summary>
        /// <returns></returns>
        private bool ValidarCodigoCliente()
        {
            if (!Validacion.EsVacio(txtCliente, miError, ClienteReq))
            {
                if (Validacion.ConFormato(Validacion.TipoValidacion.NumeroGuion, txtCliente,
                    miError, ClienteFormato))
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
            else
            {
                return false;
            }
        }

        /// <summary>
        /// Valida se el cliente ingresado existe en base de datos.
        /// </summary>
        /// <returns></returns>
        private bool ExisteCliente()
        {
            try
            {
                return miBussinesCliente.ExisteCliente(txtCliente.Text);
            }
            catch (Exception ex)
            {
                OptionPane.MessageError(ex.Message);
                return false;
            }
        }

        /// <summary>
        /// Verifica si el texto ingresado equivale a un número o palabra. Retorna true si es un número.
        /// </summary>
        /// <returns></returns>
        private bool CodigoOrString()
        {
            try
            {
                Convert.ToInt64(txtCodigoArticulo.Text);
                return true;
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// Valida si codigo ingresado existe en la base de datos.
        /// </summary>
        /// <param name="codigo">Codigo a verificar.</param>
        /// <returns></returns>
        private bool ExisteProducto(string codigo)
        {
            try
            {
                var barras = miBussinesProducto.ExisteCodigoBarras(codigo);
                var code = miBussinesProducto.ExisteCodigo(codigo);
                if (barras || code)
                    return true;
                else
                    return false;
            }
            catch (Exception ex)
            {
                OptionPane.MessageError(ex.Message);
                return false;
            }
        }

        /// <summary>
        /// Carga en memoria los datos del Producto consultado segun su codigo.
        /// </summary>
        private bool CargarProducto()
        {
            var resultado = false;
            try
            {
                ArrayProducto = miBussinesProducto.ProductoBasico(txtCodigoArticulo.Text);
                MiProducto = (Producto)ArrayProducto[0];
                var tabla = miBussinesMedida.MedidasDeProducto(MiProducto.CodigoInternoProducto);
                if (!MiProducto.AplicaTalla)
                {
                    miMedida = (ValorUnidadMedida)ArrayProducto[1];
                    SingleSize = true;
                }
                else
                {
                    
                    if (tabla.Rows.Count == 1)
                    {
                        var q = (from d in tabla.AsEnumerable()
                                 select d).Single();
                        //miMedida.IdValorUnidadMedida = Convert.ToInt32(q["idvalor_unidad_medida"]);
                        miTallaYcolor.IdTalla = Convert.ToInt32(q["idvalor_unidad_medida"]);
                        q = null;
                        SingleSize = true;
                    }
                    else
                    {
                        SingleSize = false;
                    }
                    //tabla.Clear();
                    //tabla = null;
                }
                if (MiProducto.AplicaColor)
                {
                    if (tabla.Rows.Count == 1)
                    {
                        var q = (from d in tabla.AsEnumerable()
                                 select d).Single();
                        var tablaColor = miBussinesColor.ColoresDeProducto
                            (MiProducto.CodigoInternoProducto, Convert.ToInt32(q["idvalor_unidad_medida"]));
                        if (tablaColor.Rows.Count == 1)
                        {
                            var c = (from d in tablaColor.AsEnumerable()
                                     select d).Single();
                            miTallaYcolor.IdColor = Convert.ToInt32(c["idcolor"]);
                            SingleColor = true;
                        }
                        else
                        {
                            SingleColor = false;
                        }
                    }
                    else
                    {
                        SingleColor = false;
                    }
                }
                else
                {
                    SingleColor = true;
                }
                lblDatosProducto.Text = MiProducto.NombreProducto + "  --  " + MiProducto.NombreMarca;
                if (!MiProducto.AplicaTalla && !MiProducto.AplicaColor)
                {
                    btnTallaYcolor.Enabled = false;
                }
                else
                {
                    btnTallaYcolor.Enabled = true;
                }
                txtCantidad.Text = txtCantidad.Text.Replace('.', ',');
                if (!MiProducto.CantidadDecimal)
                {
                    try
                    {
                        Convert.ToInt32(txtCantidad.Text);
                        miError.SetError(txtCantidad, null);
                        resultado = true;
                        //EstructurarConsulta();
                    }
                    catch
                    {
                        OptionPane.MessageError("Este Producto no admite cantidad en decimal.");
                        miError.SetError(txtCantidad, "Este Producto no admite cantidad en decimal.");
                        txtCantidad.Focus();
                        txtCantidad.SelectAll();
                        resultado = false;
                    }
                }
                else
                {
                    miError.SetError(txtCantidad, null);
                    resultado = true;
                    //EstructurarConsulta();
                }
            }
            catch (Exception ex)
            {
                OptionPane.MessageError(ex.Message);
            }
            return resultado;
        }

        /// <summary>
        /// Carga el listado de los descuentos relacionados a un Producto.
        /// </summary>
        private void CargarDescuentosORecargos()
        {
            if (IdDesctoRecgo == 1) ///Descuento a factura
            {
                if (rbtnDesctoProducto.Checked)
                {
                    try
                    {
                        cbDescuentoProducto.DataSource =
                            miBussinesDescuento.ListadoDescuento();//ListadoDescuento(MiProducto.CodigoInternoProducto);
                    }
                    catch (Exception ex)
                    {
                        OptionPane.MessageError(ex.Message);
                    }
                }
            }
            else                   ///Recargo a factura
            {
                if (rbtnDesctoProducto.Checked)
                {
                    try
                    {
                        cbRecargoProducto.DataSource =
                            miBussinesRecargo.ListadoRecargo();//ListadoDeRecargo(MiProducto.CodigoInternoProducto);
                    }
                    catch (Exception ex)
                    {
                        OptionPane.MessageError(ex.Message);
                    }
                }
            }
        }
        private bool Venta = false;
        /// <summary>
        /// Completa la secuencia de datos de un formulario de estención.
        /// </summary>
        /// <param name="args">Objeto que encapsula la información del formulario.</param>
        void CompletaEventos_Completo(CompletaArgumentosDeEvento args)
        {
            try
            {
                miTallaYcolor = (TallaYcolor)args.MiObjeto;
                EstructurarConsulta();
            }
            catch { }

            try
            {
                if (Venta)
                {
                    miFormasPago = (List<DTO.Clases.FormaPago>)args.MiObjeto;
                    CargarYguardarFactura();
                    Venta = false;
                }
            }
            catch { }

            try
            {
                if (Convert.ToBoolean(args.MiObjeto))
                {
                    txtCliente_KeyPress(this.txtCliente, new KeyPressEventArgs((char)Keys.Enter));
                }
                else
                {
                    ClienteMatch = false;
                    //txtCliente.Focus();
                    txtCodigoArticulo.Focus();
                }
                ExtendForms = false;
            }
            catch { }

            try
            {
                txtCliente.Text = (string)args.MiObjeto;
                txtCliente_KeyPress(this.txtCliente, new KeyPressEventArgs((char)Keys.Enter));
            }
            catch { }

            
        }

        void CompletaEventosm_Completo(CompletaArgumentosDeEventom args)
        {
            try
            {
                var producto = (Producto)args.MiMarca;
                txtCodigoArticulo.Text = producto.CodigoInternoProducto;
                txtCodigoArticulo_KeyPress(this.txtCodigoArticulo, new KeyPressEventArgs((char)Keys.Enter));
            }
            catch { }
        }

        /// <summary>
        /// Estructura la información en la tabla de memoria para ser visualizada.
        /// </summary>
        private void EstructurarConsulta()
        {
            var inventario = new DTO.Clases.Inventario();
            inventario.CodigoProducto = MiProducto.CodigoInternoProducto;
            Contador++;
            var row = miTabla.NewRow();
            row["Save"] = true;
            if (MiProducto.AplicaTalla)
            {
                inventario.IdMedida = miTallaYcolor.IdTalla;
                row["Unidad"] = "Talla";
                row["IdMedida"] = miTallaYcolor.IdTalla;
                row["Medida"] = miTallaYcolor.Talla;
            }
            else
            {
                inventario.IdMedida = miMedida.IdValorUnidadMedida;
                row["Unidad"] = miMedida.DescripcionUnidadMedida;
                row["IdMedida"] = miMedida.IdValorUnidadMedida;
                row["Medida"] = miMedida.DescripcionValorUnidadMedida;
            }
            if (MiProducto.AplicaColor)
            {
                inventario.IdColor = miTallaYcolor.IdColor;
                row["IdColor"] = miTallaYcolor.IdColor;
                row["Color"] = miTallaYcolor.Color;
            }
            else
            {
                row["IdColor"] = 0;
                row["Color"] = null;
            }
            if (MiProducto.AplicaPrecioPorcentaje)
            {
                try
                {
                    inventario.Cantidad = NumeroDeFacturas;
                    if (Promedio)
                    {
                        MiProducto.ValorVentaProducto = miBussinesProducto.PromedioValorProducto(inventario);
                    }
                    else
                    {
                        MiProducto.ValorVentaProducto = miBussinesProducto.UltimoValorProducto(inventario);
                    }
                }
                catch (Exception ex)
                {
                    OptionPane.MessageError(ex.Message);
                }
            }

            row["Id"] = Contador;
            row["Codigo"] = MiProducto.CodigoInternoProducto;
            row["Articulo"] = MiProducto.NombreProducto;
            row["Cantidad"] = txtCantidad.Text;
            row["ValorUnitario"] = MiProducto.ValorVentaProducto;

            if (IdDesctoRecgo == 1)
            {
                if (rbtnDesctoProducto.Checked)
                {
                    row["Descuento"] =
                        ((DTO.Clases.Descuento)cbDescuentoProducto.SelectedItem).ValorDescuento.ToString() + "%";
                }
                else
                {
                    row["Descuento"] = txtDescuentoFactura.Text + "%";
                }
                row["ValorMenosDescto"] = Convert.ToDouble(Convert.ToInt32(row["ValorUnitario"]) -
                    (Convert.ToInt32(row["ValorUnitario"]) * UseObject.RemoveCharacter(row["Descuento"].ToString(), '%') / 100));
            }
            else
            {
                if (rbtnDesctoProducto.Checked)
                {
                    row["Descuento"] =
                        ((DTO.Clases.Recargo)cbRecargoProducto.SelectedItem).ValorRecargo.ToString() + "%";
                }
                else
                {
                    row["Descuento"] = txtDescuentoFactura.Text + "%";
                }
                row["ValorMenosDescto"] = Convert.ToDouble(Convert.ToInt32(row["ValorUnitario"]) +
                     (Convert.ToInt32(row["ValorUnitario"]) * UseObject.RemoveCharacter(row["Descuento"].ToString(), '%') / 100));
            }

            if(miEmpresa.Regimen.IdRegimen == 1)  //Comun
            {
                row["Iva"] = MiProducto.ValorIva.ToString() + "%";
            }
            else
            {
                row["Iva"] = 0 + "%";
            }
            row["TotalMasIva"] = (Convert.ToDouble(row["ValorMenosDescto"]) *
                                  UseObject.RemoveCharacter(row["Iva"].ToString(), '%') / 100) +
                                  Convert.ToDouble(row["ValorMenosDescto"]);
            row["Valor"] = Convert.ToDouble(row["TotalMasIva"]) *
                           Convert.ToDouble(row["Cantidad"]);//txtCantidad.Text);
            
            miTabla.Rows.Add(row);
            txtTotal.Text = UseObject.InsertSeparatorMil
                (
                   Convert.ToInt32(
                   miTabla.AsEnumerable().Sum(s => s.Field<double>("Valor"))
                   ).ToString()
                );
            RecargarGridview();
            LimpiarCampos();
            LoadColorSize = false;
            btnTallaYcolor.Enabled = false;
        }

        /// <summary>
        /// Recarga el DataGridView Productos segun los datos en el DataTable miTable.
        /// </summary>
        private void RecargarGridview()
        {
            IEnumerable<DataRow> query = from datos in miTabla.AsEnumerable()
                                         orderby datos.Field<int>("Id") descending
                                         select datos;
            DataTable copy = query.CopyToDataTable<DataRow>();
            miBindingSource.DataSource = copy;
        }

        /// <summary>
        /// Limpia los campos de Producto del Formulario.
        /// </summary>
        private void LimpiarCampos()
        {
            this.txtCodigoArticulo.Focus();
            this.txtCodigoArticulo.Text = "";
            txtCantidad.Text = "1";
            if (cbDescuentoProducto.Enabled)
            {
                cbDescuentoProducto.SelectedIndex = 0;
            }
            if (cbRecargoProducto.Enabled)
            {
                cbRecargoProducto.SelectedIndex = 0;
            }
            //cbDescuentoProducto.DataSource = null;
            //cbRecargoProducto.DataSource = null;
            //lblDatosProducto.Text = "";
            MiProducto = null;
            miTallaYcolor.IdColor = 0;
            miTallaYcolor.IdTalla = 0;
            miTallaYcolor.Talla = "";
            miTallaYcolor.Color = null;
        }

        /// <summary>
        /// Actualiza la información de la factura cuando se realiza un cambio en ella.
        /// </summary>
        /// <param name="rowIndex">Índex del registro de la lista a modificar.</param>
        /// <param name="valor">Valor a modificar en el registro seleccionado.</param>
        private void ActualizarInformacion(int rowIndex, string valor)
        {
            var id = Convert.ToInt32(dgvListaArticulos.Rows[rowIndex].Cells["Id"].Value);
            var query = (from datos in miTabla.AsEnumerable()
                         where datos.Field<int>("Id") == id
                         select datos).Single();
            var index = miTabla.Rows.IndexOf(query);
            miTabla.Rows[index]["ValorUnitario"] = valor;
            miTabla.Rows[index]["ValorMenosDescto"] =
                Convert.ToDouble(Convert.ToInt32(miTabla.Rows[index]["ValorUnitario"]) +
                (Convert.ToInt32(miTabla.Rows[index]["ValorUnitario"]) *
                UseObject.RemoveCharacter(miTabla.Rows[index]["Descuento"].ToString(), '%') / 100));

            miTabla.Rows[index]["TotalMasIva"] =
                (Convert.ToDouble(miTabla.Rows[index]["ValorMenosDescto"]) *
                UseObject.RemoveCharacter(miTabla.Rows[index]["Iva"].ToString(), '%') / 100) +
                Convert.ToDouble(miTabla.Rows[index]["ValorMenosDescto"]);

            miTabla.Rows[index]["Valor"] =
                Convert.ToDouble(miTabla.Rows[index]["TotalMasIva"]) *
                Convert.ToDouble(miTabla.Rows[index]["Cantidad"]);

            RecargarGridview();
            txtTotal.Text = UseObject.InsertSeparatorMil
                (
                   Convert.ToInt32(
                   miTabla.AsEnumerable().Sum(s => s.Field<double>("Valor"))
                   ).ToString()
                );
            dgvListaArticulos.Focus();
            txtCodigoArticulo.Focus();
        }

        private void RealizarVenta()
        {
            if (dgvListaArticulos.RowCount != 0)
            {
                if (IdEstado == 1)
                {
                    if (!ExtendForms)
                    {
                        Venta = true;
                        var frmCancelarVenta = new FrmCancelarVenta();
                        frmCancelarVenta.txtTotal.Text = txtTotal.Text;
                        frmCancelarVenta.MdiParent = this.MdiParent;
                        frmCancelarVenta.Show();
                    }
                }
                else
                {
                    DialogResult rta = MessageBox.Show("¿Esta seguro de querer hacer la venta?", "Factura Venta",
                        MessageBoxButtons.YesNo, MessageBoxIcon.Question);
                    if (rta.Equals(DialogResult.Yes))
                    {
                        CargarYguardarFactura();
                    }
                }
            }
            else
            {
                OptionPane.MessageInformation("Debe cargar al menos un producto para realizar la venta.");
            }
        }

        private int MaxArticulosPrint { get { return 15; } }
        private List<PrintFactura> Facturas { set; get; }
        private bool ClienteMatch = false;

        private void CargarYguardarFactura()
        {
            dtpFechaLimite_Validating(this.dtpFechaLimite, new CancelEventArgs(false));
            if (IdEstado != 1)
            {
                if (NitCliente.Equals("1"))
                {
                    OptionPane.MessageError("Por favor ingrese un cliente.");
                    miError.SetError(txtCliente, "Por favor ingrese un cliente.");
                    ClienteMatch = false;
                }
                else
                {
                    miError.SetError(txtCliente, "");
                    ClienteMatch = true;
                }
            }
            else
            {
                miError.SetError(txtCliente, "");
                ClienteMatch = true;
            }
            if (ClienteMatch && LimiteMatch)
            {
                /*if (Edicion)
                {
                    miFactura.Numero = lblNoFactura.Text;
                }*/
                int iteracion = dgvListaArticulos.RowCount / MaxArticulosPrint;
                if (dgvListaArticulos.RowCount % MaxArticulosPrint != 0)
                {
                    iteracion++;
                }
                Facturas = new List<PrintFactura>();
                for (int i = 1; i <= iteracion; i++)
                {
                    /*if (!Edicion)
                    {
                        ObtenerNumero();
                    }
                    var contado_ = true;*/
                    if (IdEstado != 3)  //Contado o Crédito
                    {
                        ObtenerNumero();
                        //contado_ = false;
                    }
                    else   //Pendiente
                    {
                        miFactura.Numero = ObtenerNumeroTemp();
                    }
                    Facturas.Add(new PrintFactura
                    {
                        Numero = miFactura.Numero,
                        Descuento = miFactura.AplicaDescuento,
                        Cliente = NitCliente,
                        Contado = contado
                    });
                    FechaHoy = DateTime.Now;
                    miFactura.Proveedor.NitProveedor = NitCliente;
                    miFactura.Caja.Id = 1;
                    miFactura.EstadoFactura.Id = IdEstado;
                    miFactura.FormasDePago = miFormasPago;
                    miFactura.FechaIngreso = FechaHoy;
                    miFactura.FechaLimite = dtpFechaLimite.Value;
                    if (IdDesctoRecgo == 1)
                    {
                        if (rbtnDesctoFactura.Checked)
                        {
                            miFactura.Descuento = Convert.ToDouble(txtDescuentoFactura.Text);
                        }
                    }
                    else
                    {
                        if (IdDesctoRecgo == 2)
                        {
                            miFactura.AplicaDescuento = false;
                            miFactura.Recargo = Convert.ToDouble(txtDescuentoFactura.Text);
                        }
                    }
                    List<ProductoFacturaProveedor> productos = new List<ProductoFacturaProveedor>();
                    List<DataRow> miRows = new List<DataRow>();
                    var cont = 0;
                    foreach (DataRow row in miTabla.Rows)
                    {
                        cont++;
                        var producto = new ProductoFacturaProveedor();
                        producto.Save = Convert.ToBoolean(row["Save"]);
                        producto.NumeroFactura = miFactura.Numero;
                        producto.Producto.CodigoInternoProducto = row["Codigo"].ToString();
                        producto.Cantidad = Convert.ToDouble(row["Cantidad"]);
                        producto.Producto.ValorVentaProducto = Convert.ToInt32(row["ValorUnitario"]);
                        producto.Inventario.CodigoProducto = row["Codigo"].ToString();
                        producto.Inventario.IdMedida = Convert.ToInt32(row["IdMedida"]);
                        producto.Inventario.IdColor = Convert.ToInt32(row["IdColor"]);
                        producto.Inventario.Cantidad = Convert.ToDouble(row["Cantidad"]);
                        if (miFactura.AplicaDescuento)
                        {
                            producto.Producto.Descuento =
                                UseObject.RemoveCharacter(row["Descuento"].ToString(), '%');
                        }
                        else
                        {
                            producto.Producto.Recargo =
                                UseObject.RemoveCharacter(row["Descuento"].ToString(), '%');
                        }
                        producto.Producto.ValorIva =
                            UseObject.RemoveCharacter(row["Iva"].ToString(), '%');
                        productos.Add(producto);
                        miRows.Add(row);
                        if (cont == MaxArticulosPrint)
                            break;
                    }
                    miFactura.Productos = productos;
                    try
                    {
                        miBussinesFactura.IngresarFactura(miFactura, Edicion);
                        if (IdEstado == 3)
                        {
                            ActualizaNumeroTemp();
                        }
                    }
                    catch (Exception ex)
                    {
                        OptionPane.MessageError(ex.Message);
                        break;
                    }
                    foreach (DataRow miRow in miRows)
                    {
                        miTabla.Rows.Remove(miRow);
                    }
                }
                if (IdEstado != 3)
                {
                    OptionPane.MessageSuccess("La venta se realizó con éxito!");
                    DialogResult rta = MessageBox.Show("¿Desea imprimir la Factura de Venta?", "Factura Venta",
                    MessageBoxButtons.YesNo, MessageBoxIcon.Question);
                    if (rta.Equals(DialogResult.Yes))
                    {
                        foreach (PrintFactura p in Facturas)
                        {
                            Print(p.Numero, p.Descuento, p.Cliente, p.Contado);
                        }
                    }
                }
                else
                {
                    OptionPane.MessageSuccess("La venta se guardó con éxito!");
                }
                LimpiarCamposNewFactura();
                //ObtenerNumero();

            }





            ///////
            /*
            dtpFechaLimite_Validating(this.dtpFechaLimite, new CancelEventArgs(false));
            if (LimiteMatch)
            {
                if (Edicion)
                {
                    miFactura.Numero = lblNoFactura.Text;
                }
                FechaHoy = DateTime.Now;
                miFactura.Proveedor.NitProveedor = NitCliente;
                miFactura.Caja.Id = 1;
                miFactura.EstadoFactura.Id = IdEstado;
                miFactura.FormasDePago = miFormasPago;
                miFactura.FechaIngreso = FechaHoy;
                miFactura.FechaLimite = dtpFechaLimite.Value;
                if (IdDesctoRecgo == 1)
                {
                    if (rbtnDesctoFactura.Checked)
                    {
                        miFactura.Descuento = Convert.ToDouble(txtDescuentoFactura.Text);
                    }
                }
                else
                {
                    if (IdDesctoRecgo == 2)
                    {
                        miFactura.AplicaDescuento = false;
                        miFactura.Recargo = Convert.ToDouble(txtDescuentoFactura.Text);
                    }
                }
                List<ProductoFacturaProveedor> productos = new List<ProductoFacturaProveedor>();
                foreach (DataRow row in miTabla.Rows)
                {
                    var producto = new ProductoFacturaProveedor();
                    producto.Save = Convert.ToBoolean(row["Save"]);
                    producto.NumeroFactura = miFactura.Numero;
                    producto.Producto.CodigoInternoProducto = row["Codigo"].ToString();
                    producto.Cantidad = Convert.ToInt32(row["Cantidad"]);
                    producto.Producto.ValorVentaProducto = Convert.ToInt32(row["ValorUnitario"]);
                    producto.Inventario.CodigoProducto = row["Codigo"].ToString();
                    producto.Inventario.IdMedida = Convert.ToInt32(row["IdMedida"]);
                    producto.Inventario.IdColor = Convert.ToInt32(row["IdColor"]);
                    producto.Inventario.Cantidad = Convert.ToInt32(row["Cantidad"]);
                    if (miFactura.AplicaDescuento)
                    {
                        producto.Producto.Descuento =
                            UseObject.RemoveCharacter(row["Descuento"].ToString(), '%');
                    }
                    else
                    {
                        producto.Producto.Recargo =
                            UseObject.RemoveCharacter(row["Descuento"].ToString(), '%');
                    }
                    producto.Producto.ValorIva =
                        UseObject.RemoveCharacter(row["Iva"].ToString(), '%');
                    productos.Add(producto);
                }
                miFactura.Productos = productos;
                try
                {
                    miBussinesFactura.IngresarFactura(miFactura, Edicion);
                    if (IdEstado != 3)
                    {
                        OptionPane.MessageSuccess("La venta se realizó con éxito!");
                        DialogResult rta = MessageBox.Show("¿Desea imprimir la Factura de Venta?", "Factura Venta",
                        MessageBoxButtons.YesNo, MessageBoxIcon.Question);
                        if (rta.Equals(DialogResult.Yes))
                        {
                            Print();
                        }
                    }
                    else
                    {
                        OptionPane.MessageSuccess("La venta se guardó con éxito!");
                    }
                    LimpiarCamposNewFactura();
                    ObtenerNumero();
                }
                catch (Exception ex)
                {
                    OptionPane.MessageError(ex.Message);
                }
            }*/
        }

        private void LimpiarCamposNewFactura()
        {
            while (dgvListaArticulos.RowCount != 0)
            {
                dgvListaArticulos.Rows.RemoveAt(0);
            }
            txtCliente.Text = "1";
            NitCliente = "1";
            txtNombreCliente.Text = "Cliente General";
            //txtCliente_KeyPress(this.txtCliente, new KeyPressEventArgs((char)Keys.Enter));
            txtCantidad.Text = "1";
            txtTotal.Text = "0";
            tsCbContado.ComboBox.SelectedIndex = 0;
            tsCbDesctoRecargo.ComboBox.SelectedIndex = 0;
            miTabla.Clear();
            txtCodigoArticulo.Focus();
        }

        private void CargarFacturaEdicion()
        {
            tsCbContado.ComboBox.SelectedValue = Factura.EstadoFactura.Id;
            if (Factura.AplicaDescuento)
            {
                tsCbDesctoRecargo.ComboBox.SelectedValue = 1;
            }
            else
            {
                tsCbDesctoRecargo.ComboBox.SelectedValue = 2;
            }
            NitCliente = Factura.Proveedor.NitProveedor;
            txtCliente.Text = Factura.Proveedor.NitProveedor;
            txtNombreCliente.Text = Factura.Proveedor.NombreProveedor;
            //txtCliente_KeyPress(this.txtCliente, new KeyPressEventArgs((char)Keys.Enter));
            //lblNoFactura.Text = Factura.Numero;
            miFactura.NumeroEdit = Factura.Numero;
            FechaHoy = Factura.FechaIngreso;
            lblDataFecha.Text = FechaHoy.Day + " de " + UseDate.MesCorto(FechaHoy.Month) + " de " + FechaHoy.Year;
            miTabla = Productos;
            //miBindingSource.DataSource = Productos;
            RecargarGridview();
            txtTotal.Text = UseObject.InsertSeparatorMil
                (
                   Convert.ToInt32(
                   miTabla.AsEnumerable().Sum(s => s.Field<double>("Valor"))
                   ).ToString()
                );
            //Productos.Clear();
            //Productos = null;
        }

        
        private void Print(string numero, bool descto, string cliente, bool contado)
        {
            var dsDetalle = new DataSet();
            var dsEmpresa = new DataSet();
            var dsFactura = new DataSet();
            var dsUsuario = new DataSet();
            var dsCliente = new DataSet();
            var dsDian = new DataSet();
            try
            {
                dsDetalle = miBussinesFactura.PrintProducto(numero, descto);
                dsEmpresa = miBussinesEmpresa.PrintEmpresa();
                dsFactura = miBussinesFactura.PrintFacturaVenta(numero);
                dsUsuario = miBussinesUsuario.PrintUsuario(numero);
                dsCliente = miBussinesCliente.PrintCliente(cliente);
                if (contado)
                {
                    dsDian = miBussinesDian.Print(true);
                }
                else
                {
                    dsDian = miBussinesDian.Print(false);
                }

                var frmPrint = new FrmPrintFactura();
                //frmPrint.MdiParent = this.MdiParent;

                frmPrint.RptvFactura.LocalReport.DataSources.Clear();
                frmPrint.RptvFactura.LocalReport.Dispose();
                frmPrint.RptvFactura.Reset();

                frmPrint.RptvFactura.LocalReport.DataSources.Add(
                    new ReportDataSource("DsDian", dsDian.Tables["TDian"]));
                frmPrint.RptvFactura.LocalReport.DataSources.Add(
                   new ReportDataSource("DsDetalle", dsDetalle.Tables["Detalle"]));
                frmPrint.RptvFactura.LocalReport.DataSources.Add(
                    new ReportDataSource("DsEmpresa", dsEmpresa.Tables["Empresa"]));
                frmPrint.RptvFactura.LocalReport.DataSources.Add(
                    new ReportDataSource("DsFacturaVenta", dsFactura.Tables["FacturaVenta"]));
                frmPrint.RptvFactura.LocalReport.DataSources.Add(
                    new ReportDataSource("DsUsuario", dsUsuario.Tables["Usuario"]));
                frmPrint.RptvFactura.LocalReport.DataSources.Add(
                    new ReportDataSource("DsCliente", dsCliente.Tables["Cliente"]));
                
                frmPrint.RptvFactura.LocalReport.ReportPath = @"..\..\Ventas\Reportes\RptFacturaVenta.rdlc";

                var pago = new ReportParameter();
                pago.Name = "pago";
                if (contado)
                {
                    pago.Values.Add("Contado");
                }
                else
                {
                    pago.Values.Add("Crédito");
                }
                frmPrint.RptvFactura.LocalReport.SetParameters(pago);

                frmPrint.RptvFactura.RefreshReport();
                frmPrint.ShowDialog();
            }
            catch (Exception ex)
            {
                OptionPane.MessageError(ex.Message);
            }
        }

        private void dtpFechaLimite_Validating(object sender, CancelEventArgs e)
        {
            if (IdEstado == 2)
            {
                if (UseDate.FechaSinHora(dtpFechaLimite.Value) > UseDate.FechaSinHora(FechaHoy))
                {
                    LimiteMatch = true;
                    miError.SetError(dtpFechaLimite, null);
                }
                else
                {
                    LimiteMatch = false;
                    OptionPane.MessageError("La fecha limite debe ser superior a la de hoy.");
                    miError.SetError(dtpFechaLimite, "La fecha limite debe ser superior a la de hoy.");
                }
            }
            else
            {
                dtpFechaLimite.Value = DateTime.Today;
                LimiteMatch = true;
                miError.SetError(dtpFechaLimite, null);
            }
        }
        private bool LimiteMatch = false;
    }

    /// <summary>
    /// Muestra los datos en una cuadricula personalizada y mejorada.
    /// </summary>
    internal class DataGridViewPlus : DataGridView
    {
        /// <summary>
        /// Procesa teclas, como TAB, ESCAPE, ENTRAR, y las teclas de dirección, usadas para
        /// controlar cuadros de diálogo.
        /// </summary>
        /// <param name="keyData">Combinación bit a bit de valores de System.Windows.Form.Keys que representan
        ///  a las teclas que se van a procesar.</param>
        /// <returns></returns>
        protected override bool ProcessDialogKey(Keys keyData)
        {
            if (keyData == Keys.Enter)
            {
                SendKeys.Send("{TAB}");
                return true;
            }
            else
            {
                return base.ProcessDialogKey(keyData);
            }
        }
    }

    internal class PrintFactura
    {
        public string Numero { set; get; }

        public bool Descuento { set; get; }

        public string Cliente { set; get; }

        public bool Contado { set; get; }
    }
}